package com.cjack.frenchexcel.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cjack.frenchexcel.config.AjaxResult;
import com.cjack.frenchexcel.config.ErrorCodeDefine;
import com.cjack.frenchexcel.config.LayPage;
import com.cjack.frenchexcel.config.PrivateConfig;
import com.cjack.frenchexcel.dao.*;
import com.cjack.frenchexcel.enumInfo.InvoiceReimbursementStatusEnum;
import com.cjack.frenchexcel.exception.CommonException;
import com.cjack.frenchexcel.exception.DataErrorException;
import com.cjack.frenchexcel.model.CloudDiskExportModel;
import com.cjack.frenchexcel.model.CloudDiskInvoiceExportModel;
import com.cjack.frenchexcel.model.CloudDiskModel;
import com.cjack.frenchexcel.request.HandBindConsumerRequest;
import com.cjack.frenchexcel.table.*;
import com.cjack.frenchexcel.util.*;
import com.github.liaochong.myexcel.core.ExcelBuilder;
import com.github.liaochong.myexcel.core.FreemarkerExcelBuilder;
import com.github.liaochong.myexcel.core.WorkbookType;
import com.google.api.client.util.Lists;
import com.sargeraswang.util.ExcelUtil.ExcelUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang.time.DateUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.zeroturnaround.zip.ZipUtil;
import org.apache.commons.lang3.StringUtils;

import javax.persistence.criteria.Predicate;
import java.io.*;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CloudDiskService {
    @Value("${file.upload.baseServerDir}")
    String baseServerDir;
    @Value("${file.upload.baseClientDir}")
    String baseClientDir;
    @Value("${file.upload.spelitor}")
    String spelitor;
    @Autowired
    private CloudDiskDao dao;
    @Autowired
    private UserDao userDao;
    @Autowired
    private ConsumerRecordDao consumerRecordDao;
    @Autowired
    private CooperativeNumberDao cooperativeNumberDao;
    @Autowired
    private UserAdminDao userAdminDao;
    @Autowired
    private SystemparamDao systemparamDao;

    public CloudDiskModel getNextUnDeal(Object adminUserId, Long id) {
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Specification<CloudDiskTable> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            predicate.getExpressions().add(cb.lessThan(root.get("id"), id));
            predicate.getExpressions().add(cb.isNull(root.get("manullyDate")));
            return predicate;
        };
        List<CloudDiskTable> all = dao.findAll(specification, sort);
        if (CollUtil.isNotEmpty(all)) {
            CloudDiskTable cloudDiskTable = all.get(0);
            return ModelUtils.copySignModel(cloudDiskTable, CloudDiskModel.class);
        }
        return null;
    }

    public List<CloudDiskModel> list(CloudDiskModel model) {
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Specification<CloudDiskTable> specification = handleConditon(model);
        List<CloudDiskTable> all = dao.findAll(specification, sort);
        List<CloudDiskModel> datas = ModelUtils.copyListModel(all, CloudDiskModel.class);
        if (StrUtil.isNotEmpty(model.getManullyDateStart())) {
            DateTime manuallyDateStart = DateUtil.parse(model.getManullyDateStart(), "yyyy-MM-dd");
            datas = datas.stream().filter(item -> Objects.nonNull(item.getManullyDate())).filter(item -> {
                try {
                    String day = item.getManullyDate().substring(0, 2);
                    String month = item.getManullyDate().substring(2, 4);
                    String year = item.getManullyDate().substring(4, 6);

                    String manuallyDate = String.format("20%s-%s-%s", year, month, day);
                    DateTime manullyDateTime = DateUtil.parse(manuallyDate, "yyyy-MM-dd");
                    return manullyDateTime.getTime() >= manuallyDateStart.getTime();
                } catch (Exception ex) {
                    log.info("getManullyDateEnd error --> item.id={} item.manullyDate={}", item.getId(), item.getManullyDate());
                }
                return false;
            }).collect(Collectors.toList());
        }
        if (StrUtil.isNotEmpty(model.getManullyDateEnd())) {
            DateTime manuallyDateEnd = DateUtil.parse(model.getManullyDateEnd(), "yyyy-MM-dd");
            datas = datas.stream().filter(item -> Objects.nonNull(item.getManullyDate())).filter(item -> {
                try {
                    String day = item.getManullyDate().substring(0, 2);
                    String month = item.getManullyDate().substring(2, 4);
                    String year = item.getManullyDate().substring(4, 6);

                    String manullyDate = String.format("20%s-%s-%s", year, month, day);
                    DateTime manullyDateTime = DateUtil.parse(manullyDate, "yyyy-MM-dd");
                    return manullyDateTime.getTime() <= manuallyDateEnd.getTime();
                } catch (Exception ex) {
                    log.info("getManullyDateEnd error --> item.id={} item.manullyDate={}", item.getId(), item.getManullyDate());
                }
                return false;
            }).collect(Collectors.toList());
        }
        return datas;
    }

    public Page<CloudDiskModel> pageList(LayPage page, CloudDiskModel model) {
        List<CloudDiskModel> list = list(model);
        List<CloudDiskModel> datas = ListUtil.page(page.getPage() - 1, page.getLimit(), list);
        Sort sort = new Sort(Sort.Direction.DESC, "id");
        Pageable pageable = new PageRequest(page.getPage() - 1, page.getLimit(), sort);
        return new PageImpl<>(datas, pageable, list.size());
    }

    public List<CloudDiskModel> listAsc(CloudDiskModel model) {
        Sort sort = new Sort(Sort.Direction.ASC, "id");
        Specification<CloudDiskTable> specification = handleConditon(model);
        List<CloudDiskModel> datas = ModelUtils.copyListModel(dao.findAll(specification, sort), CloudDiskModel.class);
        if (StrUtil.isNotEmpty(model.getManullyDateStart())) {
            DateTime manullyDateStart = DateUtil.parse(model.getManullyDateStart(), "yyyy-MM-dd");
            datas = datas.stream().filter(item -> Objects.nonNull(item.getManullyDate())).filter(item -> {
                String day = item.getManullyDate().substring(0, 2);
                String month = item.getManullyDate().substring(2, 4);
                String year = item.getManullyDate().substring(4, 6);

                String manullyDate = String.format("20%s-%s-%s", year, month, day);
                DateTime manullyDateTime = null;
                try {
                    manullyDateTime = DateUtil.parse(manullyDate, "yyyy-MM-dd");
                    return manullyDateTime.getTime() >= manullyDateStart.getTime();
                } catch (Exception e) {
                    log.error("{} {}", item.getId(), e.getMessage());
                }
                DateUtil.parse(manullyDate, "yyyy-MM-dd");
                return manullyDateTime.getTime() >= manullyDateStart.getTime();
            }).collect(Collectors.toList());
        }
        if (StrUtil.isNotEmpty(model.getManullyDateEnd())) {
            DateTime manullyDateEnd = DateUtil.parse(model.getManullyDateEnd(), "yyyy-MM-dd");
            datas = datas.stream().filter(item -> Objects.nonNull(item.getManullyDate())).filter(item -> {
                String day = item.getManullyDate().substring(0, 2);
                String month = item.getManullyDate().substring(2, 4);
                String year = item.getManullyDate().substring(4, 6);

                String manullyDate = String.format("20%s-%s-%s", year, month, day);
                DateTime manullyDateTime = DateUtil.parse(manullyDate, "yyyy-MM-dd");
                return manullyDateTime.getTime() <= manullyDateEnd.getTime();
            }).collect(Collectors.toList());
        }
        return datas;
    }

    //导出excel
    public JSONObject exportAsExcel(CloudDiskModel model) {
        String fileType = "consumerExportExcel";
        //先创建excel空文件
        String fileName = FileUtils.getXlsxFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        File dest = new File(destDir + spelitor + fileName);
        //需要导出的数据
        List<CloudDiskModel> records = list(model);
        List<CloudDiskExportModel> exportDatas = build(records);
        //导出的列 title信息
        Map<String, String> col = CloudDiskExportModel.getColMap();
        OutputStream out;
        try {
            out = new FileOutputStream(dest);
            ExcelUtil.exportExcel(col, exportDatas, out);
            out.close();
        } catch (FileNotFoundException e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        } catch (Exception e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        }

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", exportDatas.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }

    // 税务导出
    public JSONObject invoiceExportAsExcel(CloudDiskModel model) throws CommonException {
        String fileType = "consumerExportExcel";
        //先创建excel空文件
        String fileName = FileUtils.getXlsxFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        File dest = new File(destDir + spelitor + fileName);
        //需要导出的数据
        List<CloudDiskModel> records = list(model);
        List<CloudDiskInvoiceExportModel> exportDatas = buildInvoiceExportData(records);

        //导出的列 title信息
        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put("dataList", exportDatas);
        OutputStream out = null;
        Workbook workbook = null;
        try (ExcelBuilder excelBuilder = new FreemarkerExcelBuilder()) {
            workbook = excelBuilder.workbookType(WorkbookType.XLSX).classpathTemplate("/template/invoiceExport.ftl").build(dataMap);
            out = new FileOutputStream(dest);
            workbook.write(out);
            workbook.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        } catch (IOException e) {
            e.printStackTrace();
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "导出excel失败");
        } finally {
            try {
                if (workbook != null) {
                    workbook.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", records.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }

    //下载发票
    public JSONObject exportInvoice(CloudDiskModel model) {
        String fileType = "invoiceExportZip";
        //先创建excel空文件
        String fileName = FileUtils.getZipFileName();
        String dumic = fileType + spelitor + FileUtils.getDirByDate();//动态的这一截路径
        //服务器保存文件的目录
        String destDir = baseServerDir + dumic;
        //供浏览器客户端访问的目录
        String clientDir = baseClientDir + dumic;
        //处理目录不存在则创建
        FileUtils.handleDir(destDir);
        String finalPdfPath = destDir + spelitor + FileUtils.getPdfFileName();
        String zipPath = destDir + spelitor + fileName;
        //需要导出的数据
        List<CloudDiskModel> exportDatas = listAsc(model);
        //todo 根据日期进行排序 asc升序
        for (CloudDiskModel item : exportDatas) {
            try {
                //计算出排序字段
                String jobNumber = item.getJobNumber();
                String cloudDiskNoProFix = item.getCloudDiskNoProfix();
                String cloudDiskNoNumber = String.valueOf(item.getCloudDiskNoNumber());
                if (StringUtils.isAnyBlank(jobNumber, cloudDiskNoProFix)) {
                    continue;
                }
                if (cloudDiskNoNumber == null) {
                    continue;
                }
                if (cloudDiskNoProFix.indexOf(jobNumber) != 0) {
                    continue;
                }
                String partSortNum = cloudDiskNoProFix.substring(jobNumber.length());
                int zeroLength = 4 - cloudDiskNoNumber.length();
                String zeroStr = "";
                for (int i = 0; i < zeroLength; i++) {
                    zeroStr = zeroStr + "0";
                }
                String sortNum = partSortNum + zeroStr + cloudDiskNoNumber;
                item.setSortFiled(Long.parseLong(sortNum));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        exportDatas = exportDatas.stream().sorted(Comparator.comparing(CloudDiskModel::getSortFiled)).collect(Collectors.toList());
        List<String> pdfs = new ArrayList<>();
        for (CloudDiskModel item : exportDatas) {
            if (StrUtil.isNotEmpty(item.getOriginFileUrl())) {
                String pdfFilePath = FileUtils.transferClientFileUrl(item.getOriginFileUrl(), "frenchApp", "/opt/service/FrenchExcelApp");
                if (org.apache.commons.lang3.StringUtils.isBlank(pdfFilePath)) {
                    pdfFilePath = FileUtils.transferClientFileUrl(item.getOriginFileUrl(), "frenchProject", "/opt/frenchProjectFile/");
                }
                if (org.apache.commons.lang3.StringUtils.isNotBlank(pdfFilePath)) {
                    pdfs.add(pdfFilePath);
                }
            }
        }
        try {
            PdfUtil.mergePDF(pdfs.toArray(new String[0]), finalPdfPath);
        } catch (Exception e) {
            throw new CommonException(ErrorCodeDefine.INTERFACE_COMMON_ERROR, "下载发票异常");
        }
        ZipUtil.packEntry(new File(finalPdfPath), new File(zipPath));

        //将导出成功的excel地址和导出数据的条数返回给客户端
        JSONObject json = new JSONObject();
        json.put("exportCount", pdfs.size());
        json.put("filePath", clientDir + spelitor + fileName);
        return json;
    }

    //这是2021.10.25这个时间客户提的问题7需求，逻辑奇怪
    public List<CloudDiskExportModel> build(List<CloudDiskModel> records) {
        //系统参数表
        SystemparamTable systemparam = systemparamDao.getFirstByIdNotNull();

        List<CloudDiskExportModel> exportDatas = new ArrayList<>();
        for (CloudDiskModel record : records) {
            //查询合作商信息
            CooperativeNumberTable cooperativeNumber =
                    cooperativeNumberDao.getByNameAndJobNumber(record.getCooperativeName(), record.getJobNumber());

            List<CloudDiskExportModel> currentItemList = Lists.newArrayList();

            //第一行
            CloudDiskExportModel one = buildBase(record);
            if (NumberUtil.isNumber(record.getMount())) {
                one.setCredit(NumberUtil.toBigDecimal(record.getMount()));
            }
            if (cooperativeNumber != null) {
                one.setCodeCompta(cooperativeNumber.getNumber());
                one.setAddress(cooperativeNumber.getAddress());
                one.setSiren(cooperativeNumber.getSiren());
            }
            currentItemList.add(one);

            if (!StringUtils.isEmpty(record.getHtTwenty())) {
                //第二行  HT20的值
                CloudDiskExportModel two = buildBase(record);

                if (NumberUtil.isNumber(record.getHtTwenty())) {
                    BigDecimal htTwenty = NumberUtil.toBigDecimal(record.getHtTwenty());
                    two.setDebit(htTwenty);
                }
                if (cooperativeNumber != null) {
                    two.setCodeCompta(cooperativeNumber.getCodeHt20Rule());
                }
                currentItemList.add(two);

                //第三行  HT20*tva的值
                CloudDiskExportModel three = buildBase(record);
                if (NumberUtil.isNumber(record.getTvaTwenty())) {
                    three.setDebit(NumberUtil.toBigDecimal(record.getTvaTwenty()));
                }
                three.setCodeCompta(systemparam.getT20());
                currentItemList.add(three);
            }
            if (!StringUtils.isEmpty(record.getHtTen())) {
                //第四行  HT10的值
                CloudDiskExportModel four = buildBase(record);
                if (NumberUtil.isNumber(record.getHtTen())) {
                    four.setDebit(NumberUtil.toBigDecimal(record.getHtTen()));
                }
                if (cooperativeNumber != null) {
                    four.setCodeCompta(cooperativeNumber.getCodeHt10Rule());
                }
                currentItemList.add(four);

                //第五行  HT10*tva的值
                CloudDiskExportModel five = buildBase(record);
                if (NumberUtil.isNumber(record.getTvaTen())) {
                    five.setDebit(NumberUtil.toBigDecimal(record.getTvaTen()));
                }
                five.setCodeCompta(systemparam.getT10());
                currentItemList.add(five);
            }
            if (!StringUtils.isEmpty(record.getHtFive())) {
                //第六行  HT5.5的值
                CloudDiskExportModel six = buildBase(record);
                if (NumberUtil.isNumber(record.getHtFive())) {
                    six.setDebit(NumberUtil.toBigDecimal(record.getHtFive()));
                }
                if (cooperativeNumber != null) {
                    six.setCodeCompta(cooperativeNumber.getCodeHt5Rule());
                }
                currentItemList.add(six);

                //第七行  HT5.5*tva的值
                CloudDiskExportModel seven = buildBase(record);
                if (NumberUtil.isNumber(record.getTvaFive())) {
                    seven.setDebit(NumberUtil.toBigDecimal(record.getTvaFive()));
                }
                seven.setCodeCompta(systemparam.getT5_5());
                currentItemList.add(seven);
            }
            if (!StringUtils.isEmpty(record.getHtTwo())) {
                //第八行  HT2.1的值
                CloudDiskExportModel eight = buildBase(record);
                if (NumberUtil.isNumber(record.getHtTwo())) {
                    eight.setDebit(NumberUtil.toBigDecimal(record.getHtTwo()));
                }
                if (cooperativeNumber != null) {
                    eight.setCodeCompta(cooperativeNumber.getCodeHt2Rule());
                }
                currentItemList.add(eight);

                //第九行  HT2.1*tva的值
                CloudDiskExportModel night = buildBase(record);
                if (NumberUtil.isNumber(record.getTvaTwo())) {
                    night.setDebit(NumberUtil.toBigDecimal(record.getTvaTwo()));
                }
                night.setCodeCompta(systemparam.getT2_1());
                currentItemList.add(night);
            }
            if (!StringUtils.isEmpty(record.getHtZero())) {
                //第十行  HT0*tva的值
                CloudDiskExportModel zero = buildBase(record);
                if (NumberUtil.isNumber(record.getHtZero())) {
                    zero.setDebit(NumberUtil.toBigDecimal(record.getHtZero()));
                }
                if (cooperativeNumber != null) {
                    zero.setCodeCompta(cooperativeNumber.getCodeHt0Rule());
                }
                currentItemList.add(zero);
            }

            BigDecimal diff = getDiff(record);
            if (CollUtil.isNotEmpty(currentItemList) && currentItemList.size() > 1) {
                CloudDiskExportModel cloudDiskExportModel = currentItemList.get(1);
                cloudDiskExportModel.setDebit(NumberUtil.add(cloudDiskExportModel.getDebit(), diff));
            }
            exportDatas.addAll(currentItemList);
        }
        return exportDatas;
    }

    public List<CloudDiskInvoiceExportModel> buildInvoiceExportData(List<CloudDiskModel> records) {
        List<CloudDiskInvoiceExportModel> exportDatas = new ArrayList<>();
        for (CloudDiskModel record : records) {
            CloudDiskInvoiceExportModel model = new CloudDiskInvoiceExportModel();
            model.setInvoiceNum(record.getInvoiceNum());
            model.setHtTwenty(record.getHtTwenty());
            model.setTvaTwenty(record.getTvaTwenty());
            model.setMount(record.getMount());
            if (StrUtil.isNotEmpty(record.getManullyDate())) {
                model.setManullyDate(DateFormatUtil.formatSpecial2(record.getManullyDate(), DateFormatUtil.DATE_RULE_14));
            }
            //查询合作商信息
            CooperativeNumberTable cooperativeNumber = cooperativeNumberDao.getByNameAndJobNumber(record.getCooperativeName(), record.getJobNumber());
            if (cooperativeNumber != null) {
                model.setName(cooperativeNumber.getName());
                model.setAddress(cooperativeNumber.getAddress());
                model.setSiren(cooperativeNumber.getSiren());
            }
            exportDatas.add(model);
        }
        return exportDatas;
    }

    /**
     * TTC = HT20+ HT10 + HT5.5 + HT2+ HT0 + TVA20 + TVA 10 +TVA 5.5 +TVA2?
     *
     * @param record
     * @return 相差金额
     */
    private BigDecimal getDiff(CloudDiskModel record) {
        BigDecimal ttc = StrUtil.isNotEmpty(record.getMount()) ? NumberUtil.toBigDecimal(record.getMount()) :
                BigDecimal.ZERO;
        BigDecimal ht20 = StrUtil.isNotEmpty(record.getHtTwenty()) ? NumberUtil.toBigDecimal(record.getHtTwenty()) :
                BigDecimal.ZERO;
        BigDecimal ht10 = StrUtil.isNotEmpty(record.getHtTen()) ? NumberUtil.toBigDecimal(record.getHtTen()) :
                BigDecimal.ZERO;
        BigDecimal ht5 = StrUtil.isNotEmpty(record.getHtFive()) ? NumberUtil.toBigDecimal(record.getHtFive()) :
                BigDecimal.ZERO;
        BigDecimal ht2 = StrUtil.isNotEmpty(record.getHtTwo()) ? NumberUtil.toBigDecimal(record.getHtTwo()) :
                BigDecimal.ZERO;
        BigDecimal ht0 = StrUtil.isNotEmpty(record.getHtZero()) ? NumberUtil.toBigDecimal(record.getHtZero()) :
                BigDecimal.ZERO;

        BigDecimal tva20 = StrUtil.isNotEmpty(record.getTvaTwenty()) ?
                NumberUtil.toBigDecimal(record.getTvaTwenty()) : BigDecimal.ZERO;
        BigDecimal tva10 = StrUtil.isNotEmpty(record.getTvaTen()) ? NumberUtil.toBigDecimal(record.getTvaTen()) :
                BigDecimal.ZERO;
        BigDecimal tva5 = StrUtil.isNotEmpty(record.getTvaFive()) ? NumberUtil.toBigDecimal(record.getTvaFive()) :
                BigDecimal.ZERO;
        BigDecimal tva2 = StrUtil.isNotEmpty(record.getTvaTwo()) ? NumberUtil.toBigDecimal(record.getTvaTwo()) :
                BigDecimal.ZERO;

        BigDecimal mount = NumberUtil.add(ht20, ht10, ht5, ht2, ht0, tva20, tva10, tva5, tva2);
        int compare = NumberUtil.compare(ttc.doubleValue(), mount.doubleValue());
        BigDecimal diff = BigDecimal.ZERO;
        if (compare == 1) {
            diff = NumberUtil.toBigDecimal("0.01");
        } else if (compare == -1) {
            diff = NumberUtil.toBigDecimal("-0.01");
        }
        return diff;
    }

    public AjaxResult save(CloudDiskModel model) {
        Date manullyDateTime = null;
        if (org.apache.commons.lang3.StringUtils.isNotBlank(model.getManullyDate())) {
            try {
                String day = model.getManullyDate().substring(0, 2);
                String month = model.getManullyDate().substring(2, 4);
                String year = model.getManullyDate().substring(4, 6);
                String manullyDate = String.format("20%s-%s-%s", year, month, day);
                if (!DateValidator.isValidDate(manullyDate)) {
                    return AjaxResult.ERROR(ErrorCodeDefine.DATE_ERROR, ErrorCodeDefine.DATE_ERROR_MSG);
                }
                manullyDateTime = DateUtil.parseDate(manullyDate);
            } catch (Exception ex) {
                return AjaxResult.ERROR(ErrorCodeDefine.DATE_ERROR, ErrorCodeDefine.DATE_ERROR_MSG);
            }
        }
        log.info("保存云盘数据 model={}", JSON.toJSONString(model));
        AdminUserTable userTable = userAdminDao.getOne(model.getAdminUserId());
        model.setJobNumber(userTable.getJobNumber());
        SystemparamTable system = systemparamDao.getFirstByIdNotNull();
        if (system != null) {
            try {
                // 计算
                model.setHtMount(htMount(model));
                model.setTvaTwo(tvaMul(model.getHtTwo(), system.getTva2Rate()));
                model.setTvaFive(tvaMul(model.getHtFive(), system.getTva5Rate()));
                model.setTvaTen(tvaMul(model.getHtTen(), system.getTva10Rate()));
                model.setTvaTwenty(tvaMul(model.getHtTwenty(), system.getTva20Rate()));
            } catch (Exception ex) {
                log.error("计算 tva 异常", ex);
            }
        }

        if (model.getId() == null) {
            model.setAnalyseFrom("GOOGLE");
            AdminUserTable user = userDao.getOne(model.getAdminUserId());
            String dd;
            if (model.getManullyDate().length() == 6) {
                dd = model.getManullyDate().substring(2, 6);
            } else {
                dd = model.getManullyDate();
            }
            if (dd == null || dd.length() == 0) {
                dd = CustomerStringUtil.cloudDiskNoProfix();
            }
            String cloudDiskNoProfix = user.getJobNumber() + "" + dd;//生成的发票的编号， 我们电话中说的，规则是以输入的月份和年份定，不是以当前的月份和年份定
            int cloudDiskNoNumber = dao.countByCloudDiskNoProfix(cloudDiskNoProfix) + 1;
            model.setCloudDiskNoProfix(cloudDiskNoProfix);
            model.setCloudDiskNoNumber(cloudDiskNoNumber);
            CloudDiskTable table = ModelUtils.copySignModel(model, CloudDiskTable.class);
            table.setInvoiceReimbursementStatus(model.getInvoiceReimbursementStatus());
            //添加水印
            String newImgUrls = addWaterMark(table);
            table.setImgFileUrl(newImgUrls);
            //处理几个金额的计算
            //handleMount( table);
            table.setManuallyDateTime(manullyDateTime);
            dao.save(table);
        } else {
            CloudDiskTable table = dao.getOne(model.getId());
            Boolean isFirstEdit = table.getHtMount() == null;
            if (StringUtils.isEmpty(model.getImgFileUrl())) {
                model.setImgFileUrl(table.getImgFileUrl());
            }
            if (StringUtils.isEmpty(model.getOriginFileUrl())) {
                model.setOriginFileUrl(table.getOriginFileUrl());
            }
            if (StringUtils.isEmpty(model.getEntireContent())) {
                model.setEntireContent(table.getEntireContent());
            }
            if (table.getCloudDiskNoProfix() == null || table.getCloudDiskNoProfix().length() == 0) {
                AdminUserTable user = userDao.getOne(model.getAdminUserId());
                String dd;
                if (model.getManullyDate().length() == 6) {
                    dd = model.getManullyDate().substring(2, 6);
                } else {
                    dd = model.getManullyDate();
                }
                if (dd == null || dd.length() == 0) {
                    dd = CustomerStringUtil.cloudDiskNoProfix();
                }
                String cloudDiskNoProfix = user.getJobNumber() + "" + dd;//生成的发票的编号， 我们电话中说的，规则是以输入的月份和年份定，不是以当前的月份和年份定
                int cloudDiskNoNumber = dao.countByCloudDiskNoProfix(cloudDiskNoProfix) + 1;
                model.setCloudDiskNoProfix(cloudDiskNoProfix);
                model.setCloudDiskNoNumber(cloudDiskNoNumber);
            }
            //ModelUtils.copySignModel(model, table);
            extracted(model, table);
            //添加水印
            if (isFirstEdit) {
                String newImgUrls = addWaterMark(table);
                table.setImgFileUrl(newImgUrls);
            }
            //处理几个金额的计算
            //handleMount( table);
            table.setManuallyDateTime(manullyDateTime);
            dao.save(table);
        }

        return AjaxResult.SUCCESS("保存成功");
    }

    private void extracted(CloudDiskModel model, CloudDiskTable table) {
        table.setId(model.getId());
        table.setUpdateTime(model.getUpdateTime());
        if (model.getCreateTime() != null) {
            table.setCreateTime(model.getCreateTime());
        }
        table.setName(model.getName());
        table.setOriginFileUrl(model.getOriginFileUrl());
        table.setImgFileUrl(model.getImgFileUrl());
        table.setMount(model.getMount());
        table.setContentType(model.getContentType());
        table.setAnalyseFrom(model.getAnalyseFrom());
        table.setEntireContent(model.getEntireContent());
        table.setValidContent(model.getValidContent());
        table.setOtherId(model.getOtherId());
        table.setCloudDiskNoProfix(model.getCloudDiskNoProfix());
        if (model.getCloudDiskNoNumber() != null) {
            table.setCloudDiskNoNumber(model.getCloudDiskNoNumber());
        }
        table.setAdminUserId(model.getAdminUserId());
        table.setJobNumber(model.getJobNumber());
        table.setCustomHouse(model.getCustomHouse());
        table.setCooperativeName(model.getCooperativeName());
        table.setInvoiceNum(model.getInvoiceNum());
        table.setHtMount(model.getHtMount());
        table.setTvaTwenty(model.getTvaTwenty());
        table.setTvaTen(model.getTvaTen());
        table.setTvaFive(model.getTvaFive());
        table.setTvaTwo(model.getTvaTwo());
        table.setTvaZero(model.getTvaZero());
        table.setHtTwenty(model.getHtTwenty());
        table.setHtTen(model.getHtTen());
        table.setHtFive(model.getHtFive());
        table.setHtTwo(model.getHtTwo());
        table.setHtZero(model.getHtZero());
        table.setManullyDate(model.getManullyDate());
        table.setInvoiceReimbursementStatus(model.getInvoiceReimbursementStatus());
    }

    private String addWaterMark(CloudDiskTable table) {
        String baseClientDir = this.baseClientDir;
        String baseServerDir = this.baseServerDir;
        String totalInvoiceImg = table.getImgFileUrl();
        if (totalInvoiceImg != null && !totalInvoiceImg.equals("")) {
            log.info("----->系统云盘：添加水印");
            String[] invoiceImgArr = totalInvoiceImg.split(";");
            log.info("---totalInvoiceImg={} ", totalInvoiceImg);
            for (int i = 0; i < invoiceImgArr.length; i++) {
                String invoiceImgUrl = invoiceImgArr[i];
                if (invoiceImgUrl != null && !invoiceImgUrl.equals("")) {
                    if (invoiceImgUrl.contains("frenchApp")) {
                        baseClientDir = "frenchApp";
                        baseServerDir = "/opt/service/FrenchExcelApp";
                    }
                    String invoiceImgPath = FileUtils.transferClientFileUrl(invoiceImgUrl, baseClientDir, baseServerDir);
                    String str = "" + table.getCloudDiskNoNumber();
                    String pad = "0000";
                    String ans = pad.substring(0, pad.length() - str.length()) + str;
                    log.info("----->prefix={} ans={}", table.getCloudDiskNoProfix(), ans);

                    // 提取文件名
                    int lastIndex = invoiceImgPath.lastIndexOf("/");
                    String fileName = invoiceImgPath.substring(lastIndex + 1);
                    // 提取文件名主体和扩展名
                    int dotIndex = fileName.lastIndexOf(".");
                    String nameWithoutExt = fileName.substring(0, dotIndex);
                    String ext = fileName.substring(dotIndex);
                    // 生成新的文件名
                    String newFileName = nameWithoutExt + "_1" + ext;
                    // 生成新的文件路径(绝对路径)
                    String newInvoiceImg = invoiceImgPath.substring(0, lastIndex + 1) + newFileName;
                    log.info("old={} new={}", invoiceImgPath, newInvoiceImg);
                    WaterMarkUtil.addWaterMark(invoiceImgPath, newInvoiceImg, table.getCloudDiskNoProfix() + ans);
                    invoiceImgArr[i] = invoiceImgUrl.replace(nameWithoutExt, nameWithoutExt + "_1");
                }
            }
            String pdfPath = FileUtils.transferClientFileUrl(table.getOriginFileUrl(), baseClientDir, baseServerDir);
            try {
                PdfUtil.mergeImgsToPdf(invoiceImgArr, pdfPath, baseServerDir);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String result = String.join(";", invoiceImgArr);
            return result.isEmpty() ? "" : result + ";";
        } else {
            return totalInvoiceImg;
        }
    }


    public static void main(String[] args) {
        String[] invoiceImgArr = new String[]{"1", "2", "3"};
        System.out.println(String.join(";", invoiceImgArr));
    }

    public void deleteOtherId(Long otherId) {
        List<CloudDiskTable> cloudDiskTables = dao.findByOtherId(otherId);
        if (cloudDiskTables == null || cloudDiskTables.size() == 0) {
            return;
        }
        for (CloudDiskTable cloudDiskTable : cloudDiskTables) {
            cloudDiskTable.setOtherId(null);
            dao.save(cloudDiskTable);
        }
    }

    public JSONObject analyseImgText(String clientImgPath) throws IOException {
        String textDate = null;//1-日期
        String textAmount = null;//2-金额
        String textCooperative = null;//3-供应商  对应供应商复杂名
        String textNumber = null;//4-发票号


        //服务端路径转化为本地文件路径
        String fileLocalPath = FileUtils.transferClientFileUrl(clientImgPath, baseClientDir, baseServerDir);
        String[] fileLocalPathArr = fileLocalPath.split(";");
        String analyseContent = "";
        for (String fileLocalPathA : fileLocalPathArr) {
            // analyseContent += GoogleVersionApi.detectText( fileLocalPathA);
        }
        /*
        //从识别出的文本内容中使用配置的表达式提取数据
        List<ImgTextExtractRuleTable> rules = imgTextExtractRuleDao.findAll();
        if( rules == null || rules.size() == 0){
            return null;
        }
        LOG.info( "开始抽取以下内容中的数据---------------------------");
        LOG.info( analyseContent);
        LOG.info( "-----------------------------------------------");
        for( ImgTextExtractRuleTable rule : rules){
            LOG.info( "应用规则[" + rule.getRuleName() + "]进行抽取");
            switch ( rule.getType()){
                case 1://日期
                    //只要有之前匹配到了，这里这一项将直接返回不再去匹配，下面几项同理
                    if( textDate == null){
                        textDate = RegUtil.extractContent( analyseContent, rule.getRule());
                    }
                    break;
                case 2://金额
                    if( textAmount == null){
                        textAmount = RegUtil.extractContent( analyseContent, rule.getRule());
                    }
                    break;
                case 3://供应商
                    if( textCooperative == null){
                        textCooperative = RegUtil.extractContent( analyseContent, rule.getRule());
                    }
                    break;
                case 4://发票号
                    if( textNumber == null){
                        textNumber = RegUtil.extractContent( analyseContent, rule.getRule());
                    }
                    break;
            }
        }
        */
        JSONObject res = new JSONObject();
        res.put("entireContent", analyseContent);
        /*
        res.put( "textDate", textDate);
        res.put( "textAmount", textAmount);
        res.put( "textCooperative", textCooperative);
        res.put( "textNumber", textNumber);*/
        return res;
    }

    public void del(String ids) {
        List<CloudDiskTable> tables = new ArrayList<>();
        String[] idArr = ids.split(",");
        for (String id : idArr) {
            CloudDiskTable table = new CloudDiskTable();
            table.setId(Long.valueOf(id));
            tables.add(table);
        }
        dao.deleteInBatch(tables);
    }

    //新上传种类 文件中含有 facture 或 ticket , invoice,  三种其中一种的， 种类变更为发票类，
    // 不含这三种字样的， 种类为其他类  。  这三种不区分大小写与字母之间的空格
    public AjaxResult autoSetType(CloudDiskModel model) {
        CloudDiskTable table = dao.getOne(model.getId());
        //不区分大小写与字母之间的空格
        String entireContent = table.getEntireContent().toUpperCase().replaceAll(" ", "");
        if (entireContent.contains("facture".toUpperCase())
                || entireContent.contains("ticket".toUpperCase())
                || entireContent.contains("invoice".toUpperCase())) {
            table.setContentType(3);
            dao.save(table);
            return AjaxResult.SUCCESS("文件类型已变更为发票");
        } else {
            table.setContentType(2);
            dao.save(table);
            return AjaxResult.SUCCESS("文件类型已变更为其他类型");
        }
    }

    //批量设置
    public AjaxResult autoSetType() {
        List<CloudDiskTable> tables = dao.findByContentType(1);
        for (CloudDiskTable table : tables) {
            autoSetType(ModelUtils.copySignModel(table, CloudDiskModel.class));
        }
        return AjaxResult.SUCCESS("操作成功");
    }

    // 解除发票对应
    public AjaxResult unBindConsumer(Long id) {
        CloudDiskTable table = dao.getOne(id);
        if (table != null && table.getOtherId() != null) {
            ConsumerRecordTable consumerRecordTable = consumerRecordDao.getOne(table.getOtherId());
            if (consumerRecordTable != null) {
                consumerRecordDao.updateFieldById(consumerRecordTable.getId());
                dao.updateFiledById(table.getId());
            }
        }
        return AjaxResult.SUCCESS("解除绑定成功");
    }

    public AjaxResult bindConsumer(CloudDiskModel model) {
        CloudDiskTable table = dao.getOne(model.getId());
        String entireContent = table.getEntireContent();
        //判断消费记录的 金额、发票号 是否同时包含在 文件提取出来的文本内容里面
        List<ConsumerRecordTable> consumers = null;
        //管理员可以对应所有文件，普通员工只能对应自己的文件
        AdminUserTable adminUserTable = userAdminDao.findOne(table.getAdminUserId());
        if (adminUserTable.getRole().getCode().equals(PrivateConfig.EMPLOEE_CODE)) {
            consumers = consumerRecordDao.findAllByInvoiceIsNullAndImportUserId(table.getAdminUserId());
        } else {
            consumers = consumerRecordDao.findAllByInvoiceIsNull();
        }

        if (consumers != null && consumers.size() != 0) {
            for (ConsumerRecordTable consumer : consumers) {
                String montantTTC = consumer.getMontantTTC();//金额


                List<CooperativeNumberTable> exsits = cooperativeNumberDao.getByName(consumer.getFournisseur());
                if (CollectionUtils.isEmpty(exsits)) {
                    continue;
                }
                CooperativeNumberTable cooperativeNumberTable = exsits.get(0);
                String taxNumber = cooperativeNumberTable.getTaxNumber();//税号，从合作商编号规则哪里查询
                taxNumber = taxNumber.replace(" ", "");
                //如果云盘文件设置列金额并且金额根消费记录对应不上，就不用比较发票内容列
                if (!consumer.getMontantTTC().contains(model.getMount())) {
                    continue;
                }
                if (checkTTCMatch(montantTTC, entireContent) && checkTaxNumberMatch(taxNumber, entireContent)) {
                    //保存云盘表
                    table.setOtherId(consumer.getId());
                    dao.save(table);
                    //保存到消费记录表
                    consumer.setInvoice(table.getOriginFileUrl());
                    consumer.setInvoiceImg(table.getImgFileUrl());
                    //TTC/6 然后四舍五入取两位小数 的数据是否出现在 GOOGLE VISION 文件中，如果出现，则把该值填充为TVA
                    DecimalFormat df = new DecimalFormat("#.00");
                    Double tvaCount = Double.valueOf(consumer.getMontantTTC().replace("-", ""));
                    String tvaStr = df.format(tvaCount / 6);
                    if (checkTvaNumberMatch(tvaStr, entireContent)) {
                        consumer.setInvoiceMoney(tvaStr);
                    }
                    consumerRecordDao.save(consumer);
                    return AjaxResult.SUCCESS("已关联到消费记录");
                }
            }
        }
        return AjaxResult.SUCCESS("未找到关联的消费记录");
    }

    //批量操作
    public AjaxResult bindConsumer() {
        List<CloudDiskTable> tables = dao.findByOtherIdIsNull();
        for (CloudDiskTable table : tables) {
            bindConsumer(ModelUtils.copySignModel(table, CloudDiskModel.class));
        }
        return AjaxResult.SUCCESS("操作成功");
    }

    public AjaxResult handBindConsumer(HandBindConsumerRequest request) {
        // 云盘记录表
        CloudDiskTable cloudDiskTable = dao.getOne(request.getId());
        // 消费记录表
        ConsumerRecordTable consumerRecordTable = consumerRecordDao.getOne(request.getOtherId());
        if (consumerRecordTable == null) {
            return AjaxResult.ERROR(500, "操作失败");
        }
        //保存云盘表
        cloudDiskTable.setOtherId(request.getOtherId());
        cloudDiskTable.setInvoiceReimbursementStatus(InvoiceReimbursementStatusEnum.REIMBURSEMENT.getCode());
        dao.save(cloudDiskTable);
        //保存到消费记录表
        consumerRecordTable.setInvoice(cloudDiskTable.getOriginFileUrl());
        consumerRecordTable.setInvoiceImg(cloudDiskTable.getImgFileUrl());
        consumerRecordTable.setInvoiceStatus("PASS");
        consumerRecordDao.save(consumerRecordTable);
        return AjaxResult.SUCCESS("操作成功");
    }

    private boolean checkTTCMatch(String ttc, String entireContent) {
        ttc = ttc.replace("-", "");
        ttc = ttc.replace(" ", "");
        String ttc1 = ttc.replace("\\.", ",");
        String ttc2 = ttc.replace(",", "\\.");
        entireContent = entireContent.replace(" ", "");
        return entireContent.contains(ttc1) || entireContent.contains(ttc2);
    }

    private boolean checkTaxNumberMatch(String taxNumber, String entireContent) {
        taxNumber = taxNumber.replace(" ", "");
        entireContent = entireContent.replace(" ", "");
        return entireContent.contains(taxNumber);
    }

    private boolean checkTvaNumberMatch(String tva, String entireContent) {
        tva = tva.replace("-", "");
        tva = tva.replace(" ", "");
        String tva1 = tva.replace("\\.", ",");
        String tva2 = tva.replace(",", "\\.");
        entireContent = entireContent.replace(" ", "");
        return entireContent.contains(tva1) || entireContent.contains(tva2);
    }


    private void handleMount(CloudDiskTable table) throws DataErrorException {
        //先根据供应商名称找到对应供应商
        List<CooperativeNumberTable> exsits = cooperativeNumberDao.getByName(table.getCooperativeName());
        if (CollectionUtils.isEmpty(exsits)) {
            return;
        }
        CooperativeNumberTable cooperativeNumberTable = exsits.get(0);
        //SystemparamTable systemparamTable = systemparamDao.getFirstByIdNotNull();
        BigDecimal mount = CustomerStringUtil.strToBigDecimal(table.getMount());
        BigDecimal htMount = CustomerStringUtil.strToBigDecimal(table.getHtMount());
        BigDecimal resultA = null;
        BigDecimal resultB = null;
        switch (CustomerStringUtil.emptyOrZeroCount(cooperativeNumberTable.getCodeHt2Rule(),
                cooperativeNumberTable.getCodeHt5Rule(), cooperativeNumberTable.getCodeHt10Rule(),
                cooperativeNumberTable.getCodeHt20Rule())) {
            case 0://情况1:4个数据全为0
                //判断 fe_clouddisk.mount - fe_clouddisk.ht_mount是否等于0
                //等于0， 则保存 ， 不为0 ，不保存，显示数据出错。
                if (!mount.subtract(htMount).equals(new BigDecimal(0))) {
                    throw new DataErrorException();
                }
                break;
            case 1://情况2:4个数据中只有一个不为0
                //直接使用和作商表的配置就可以了
                //然后取fe_systemparam表中与 code_ht ?_role对应的tva_10_rate,tva_20_rate,tva_2_rate, tva_5_rate中保存的一个整数数据， 我用
                // int_tva_?_rate来表示。
                //A  =  fe_clouddisk . ht_mount  *  int_tva_?_rate        A结果保留两位小数
                // B  =   fe_clouddisk . mount -  fe_clouddisk . ht_mount      B结果保留两位小数
                //IF   A – B =  0.01 或者0 或者 -0.01
                //那么 ，按云盘编译中的确定键， 保存数据。
                //并且，设置fe_clouddisk . tva_ ? = B, 也就是把 B 保存在fe_clouddisk . tva_ ? 中。
                //如果不属于，则显示数据出错。
                BigDecimal singleNotEmptyOrZero =
                        CustomerStringUtil.getSingleNotEmptyOrZero(cooperativeNumberTable.getCodeHt2Rule(),
                                cooperativeNumberTable.getCodeHt5Rule(), cooperativeNumberTable.getCodeHt10Rule(),
                                cooperativeNumberTable.getCodeHt20Rule());
                resultA = htMount.multiply(singleNotEmptyOrZero);
                resultB = mount.subtract(htMount);
                if (!(Math.abs(resultA.subtract(resultB).doubleValue()) <= 0.01)) {
                    throw new DataErrorException();
                }
                if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt2Rule())) {
                    table.setTvaTwo(CustomerStringUtil.bigDecimalToStr(resultB));
                } else if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt5Rule())) {
                    table.setTvaFive(CustomerStringUtil.bigDecimalToStr(resultB));
                } else if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt10Rule())) {
                    table.setTvaTen(CustomerStringUtil.bigDecimalToStr(resultB));
                } else {
                    table.setTvaTwenty(CustomerStringUtil.bigDecimalToStr(resultB));
                }
                break;
            case 2://情况3:4个数据中只有两个不为0
                //然后取fe_systemparam表中与 code_ht ?1_role与 code_ht ?2_role对应的tva_10_rate,tva_20_rate,tva_2_rate,
                // tva_5_rate两个列中保存的整数数据，
                //我分别用 int_tva_?1_rate与 int_tva_?2_rate来表示。
                BigDecimal codeHt1 = null;
                BigDecimal codeHt2 = null;
                int flag1 = 0;
                int flag2 = 0;
                if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt2Rule())) {
                    codeHt1 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt2Rule());
                    flag1 = 2;
                }
                if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt5Rule())) {
                    if (codeHt1 == null) {
                        codeHt1 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt5Rule());
                        flag1 = 5;
                    } else {
                        codeHt2 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt5Rule());
                        flag2 = 5;
                    }
                }
                if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt10Rule()) && codeHt2 == null) {
                    if (codeHt1 == null) {
                        codeHt1 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt10Rule());
                        flag1 = 10;
                    } else {
                        codeHt2 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt10Rule());
                        flag2 = 10;
                    }
                }
                if (!CustomerStringUtil.isEmptyOrZero(cooperativeNumberTable.getCodeHt20Rule()) && codeHt2 == null) {
                    if (codeHt1 == null) {
                        codeHt1 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt20Rule());
                        flag1 = 20;
                    } else {
                        codeHt2 = CustomerStringUtil.strToBigDecimal(cooperativeNumberTable.getCodeHt20Rule());
                        flag2 = 20;
                    }
                }
                //A= (  int_tva_?1_rate *  int_tva_?2_rate * fe_clouddisk . ht_mount – int_tva_?1_rate *
                // (fe_clouddisk . mount - fe_clouddisk.ht_mount) / ( int_tva_?2_rate - int_tva_?1_rate )
                //B= (  int_tva_?2_rate *  int_tva_?1_rate * fe_clouddisk . ht_mount – int_tva_?2_rate *
                // (fe_clouddisk . mount - fe_clouddisk.ht_mount) / ( int_tva_?1_rate - int_tva_?2_rate )
                resultA =
                        codeHt1.multiply(codeHt2).multiply(htMount).subtract(codeHt1.multiply(mount.subtract(htMount))).divide(codeHt2.subtract(codeHt1), 3, BigDecimal.ROUND_UP);
                resultB =
                        codeHt2.multiply(codeHt1).multiply(htMount).subtract(codeHt2.multiply(mount.subtract(htMount))).divide(codeHt1.subtract(codeHt2), 3, BigDecimal.ROUND_UP);

                //If    A > 0  and
                // B > 0 and
                //A < fe_clouddisk . ht_mount *  max ( int_tva_?1_rate, int_tva_?2_rate )  and
                // B < fe_clouddisk . ht_mount *  max ( int_tva_?1_rate, int_tva_?2_rate )
                //Then  保存， 而且
                //fe_clouddisk . tva_ ?1 = A ,      fe_clouddisk . tva_ ?2 = B 。
                //否则 ，显示数据出错。
                if (resultA.doubleValue() > 0 && resultB.doubleValue() > 0 &&
                        resultA.compareTo(htMount.multiply(codeHt1.compareTo(codeHt2) == 1 ? codeHt1 : codeHt2)) == -1 &&
                        resultB.compareTo(htMount.multiply(codeHt1.compareTo(codeHt2) == 1 ? codeHt1 : codeHt2)) == -1) {
                    switch (flag1) {
                        case 2:
                            table.setTvaTwo(CustomerStringUtil.bigDecimalToStr(resultA));
                            break;
                        case 5:
                            table.setTvaFive(CustomerStringUtil.bigDecimalToStr(resultA));
                            break;
                        case 10:
                            table.setTvaTen(CustomerStringUtil.bigDecimalToStr(resultA));
                            break;
                        case 20:
                            table.setTvaTwenty(CustomerStringUtil.bigDecimalToStr(resultA));
                            break;
                    }
                    switch (flag2) {
                        case 2:
                            table.setTvaTwo(CustomerStringUtil.bigDecimalToStr(resultB));
                            break;
                        case 5:
                            table.setTvaFive(CustomerStringUtil.bigDecimalToStr(resultB));
                            break;
                        case 10:
                            table.setTvaTen(CustomerStringUtil.bigDecimalToStr(resultB));
                            break;
                        case 20:
                            table.setTvaTwenty(CustomerStringUtil.bigDecimalToStr(resultB));
                            break;
                    }
                } else {
                    throw new DataErrorException();
                }
                break;
        }
    }

    /**
     * 组装查询条件
     *
     * @param model
     * @return
     */
    private Specification<CloudDiskTable> handleConditon(CloudDiskModel model) {
        Specification<CloudDiskTable> specification = (root, query, cb) -> {
            Predicate predicate = cb.conjunction();
            if (!StringUtils.isEmpty(model.getJobNumber())) {
                predicate.getExpressions().add(cb.like(root.get("jobNumber").as(String.class),
                        "%" + model.getJobNumber() + "%"));
            }
            if (!StringUtils.isEmpty(model.getMount())) {
                predicate.getExpressions().add(cb.like(root.get("mount").as(String.class), "%" + model.getMount() +
                        "%"));
            }
            if (model.getContentType() != null) {
                predicate.getExpressions().add(cb.equal(root.get("contentType").as(String.class),
                        model.getContentType()));
            }
            return predicate;
        };
        return specification;
    }

    private CloudDiskExportModel buildBase(CloudDiskModel record) {
        CloudDiskExportModel exportData = new CloudDiskExportModel();
        if (StrUtil.isNotEmpty(record.getManullyDate())) {
            exportData.setDate(DateFormatUtil.formatSpecial2(record.getManullyDate(), DateFormatUtil.DATE_RULE_14));
        }
        exportData.setPiece(record.getCloudDiskNoProfix() + "" + CustomerStringUtil.sendGoodsNumber(record.getCloudDiskNoNumber()));
        exportData.setLibelle(record.getCooperativeName());
        return exportData;
    }

    private String tvaMul(String ht, String tvaRate) {
        if (StrUtil.isNotEmpty(ht) && NumberUtil.isNumber(tvaRate)) {
            return NumberUtil.roundStr(NumberUtil.mul(ht, tvaRate).toString(), 2);
        }
        return null;
    }

    private String htMount(CloudDiskModel model) {
        try {
            BigDecimal htMount = new BigDecimal(0);
            if (StrUtil.isNotEmpty(model.getHtTwenty()) && NumberUtil.isNumber(model.getHtTwenty())) {
                htMount = NumberUtil.add(htMount.toString(), model.getHtTwenty());
            }
            if (StrUtil.isNotEmpty(model.getHtTen()) && NumberUtil.isNumber(model.getHtTen())) {
                htMount = NumberUtil.add(htMount.toString(), model.getHtTen());
            }
            if (StrUtil.isNotEmpty(model.getHtFive()) && NumberUtil.isNumber(model.getHtFive())) {
                htMount = NumberUtil.add(htMount.toString(), model.getHtFive());
            }
            if (StrUtil.isNotEmpty(model.getHtTwo()) && NumberUtil.isNumber(model.getHtTwo())) {
                htMount = NumberUtil.add(htMount.toString(), model.getHtTwo());
            }
            if (StrUtil.isNotEmpty(model.getHtZero()) && NumberUtil.isNumber(model.getHtZero())) {
                htMount = NumberUtil.add(htMount.toString(), model.getHtZero());
            }
            if (htMount.doubleValue() > 0) {
                return htMount.toString();
            }
        } catch (Exception ex) {
            log.error("计算ht mount 异常", ex);
        }
        return null;
    }
}
